package com.xc.quickstart.job;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.alibaba.fastjson.JSON;
import com.xc.quickstart.common.bean.ExceptionDelayQueueProcessor;
import com.xc.quickstart.common.context.ApiContext;
import com.xc.quickstart.common.event.ExceptionDelayQueueEvent;
import com.xc.quickstart.service.JobDailyReportService;
import com.xxl.job.core.biz.model.ReturnT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.time.Duration;
import java.time.Instant;
import java.util.Map;

@Slf4j
public abstract class BaseJobHandler {
    @Autowired
    private ExceptionDelayQueueProcessor exceptionDelayQueueProcessor;

    @Autowired
    private JobDailyReportService jobDailyReportService;

    @Autowired
    @Lazy
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    public void asyncExecute() {
        asyncExecute(null);
    }

    public void asyncExecute(Map<String, String> args) {
        threadPoolTaskExecutor.execute(() -> execute(args));
    }

    public ReturnT<String> execute(Map<String, String> args) {
        try {
            log.info("[执行任务][{}]开始,args:{},crmTraceId:{}", this.getJobName(), JSON.toJSONString(args), ApiContext.getCrmTraceId());
            Instant start = Instant.now();

            ReturnT<String> result = doExecute(args);

            log.info("[执行任务][{}]结束,args:{},result:{},耗时:{}ms,crmTraceId:{}", this.getJobName(), JSON.toJSONString(args)
                    , JSON.toJSONString(result)
                    , Duration.between(start, Instant.now()).toMillis()
                    , ApiContext.getCrmTraceId());

            jobDailyReportService.record(this.getClass().getName(), getJobName(), Duration.between(start, Instant.now()).toMillis(), true);
            return result;
        } catch (Exception ex) {
            log.error("[执行任务][{}]异常;args:{};msg:{},crmTraceId:{}", this.getJobName(), JSON.toJSONString(args), ExceptionUtil.stacktraceToString(ex), ApiContext.getCrmTraceId());

            jobDailyReportService.record(this.getClass().getName(), getJobName(), 0L, false);
            exceptionDelayQueueProcessor.put(new ExceptionDelayQueueEvent(this.getClass().getName(), getJobName(), ExceptionUtil.stacktraceToString(ex, 400)));
            return ReturnT.FAIL;
        }
    }

    protected abstract ReturnT<String> doExecute(Map<String, String> args);

    protected abstract String getJobName();
}
